package com.jiang.thread.apply;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

/**
 * @author jiangzhe
 * @create 2022/4/27 15:17
 */
@Slf4j(topic = "WaitAndNotify")
public class WaitAndNotify {

    static final Object lock = new Object();
    static boolean hasCigarette = false;
    static boolean hasTakeout = false;

    @Test
    public void testWaitAndNotify(){

        // 老烟枪线程
        new Thread(() -> {
            synchronized (lock){
                log.info("有烟没 {}", hasCigarette);
                // 但使用 if + wait 判断仅有一次机会，一旦条件不成立，就没有重新判断的机会了
                // 解决方法：用 while + wait，当条件不成立，再次 wait
//                if(!hasCigarette){
                while (!hasCigarette){
                    log.info("没烟，歇会");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if(hasCigarette){
                    log.info("有烟，开干");
                }else {
                    log.info("没烟，不干");
                }
            }
        }, "老烟枪").start();

        // 干饭人线程
        new Thread(() -> {
            synchronized (lock){
                log.info("外卖到没 {}", hasTakeout);
                if(!hasTakeout){
                    log.info("外卖没到，歇会");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                if(hasTakeout){
                    log.info("外卖到了，开干");
                }else {
                    log.info("外卖没到，不干");
                }
            }
        }, "干饭人").start();

        try {
            // 2s后，外卖线程也来了
            Thread.sleep(2000);
            new Thread(() -> {
                synchronized (lock){
                    hasTakeout = true;
                    log.info("外卖到了");
                    lock.notifyAll();
                }
            }, "外卖小哥").start();

            // 1s后，外卖线程又来了
            Thread.sleep(1000);
            new Thread(() -> {
                synchronized (lock){
                    hasCigarette = true;
                    log.info("烟到了");
                    lock.notifyAll();
                }
            }, "外卖小哥").start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}
